//获取画布对象
const canvas = document.getElementById("myCanvas")
//获取绘画上下文，此处是2d上下文环境
const ctx = canvas.getContext('2d')
//存放disk的容器
var disks = []

//声明全局的变量
//画布上绘制的disk的数量
var numberOfDisks
var minRadius //最小半径
var maxRadius //最大半径
var initialSpeed //初始速度
var direction //初始方向
var loopId //setInterval的id


//初始化函数
function init() {

	//指定画布大小
	canvas.width = window.innerWidth
	canvas.height = window.innerHeight
	//获取页面上的控件元素对象
	var numberBar = document.getElementById('numberOfDisks')
	var radiusMenu = document.getElementById('radius')
	var speedBar = document.getElementById('speed')
	var directionBar = document.getElementById('direction')
	var gravityBar = document.getElementById('gravity')

	//获取控件元素对象中的值
	gravity = gravityBar.value / 100
	initialSpeed = speedBar.value / 100
	numberOfDisks = numberBar.value;
	[minRadius, maxRadius] = radiusMenu.value.split(',')

	//生成disks
	generateDisks(numberOfDisks)

	//给改变数量input控件添加事件监听
	numberBar.addEventListener('change', function() {
		numberOfDisks = this.value
		resetDisks()
	})
	//给改变半径的下拉菜单添加事件监听
	radiusMenu.addEventListener('change', function() {
		[minRadius, maxRadius] = radiusMenu.value.split(',')
		resetDisks()
	})
	//给调速控件添加事件监听
	speedBar.addEventListener('change', function() {
		initialSpeed = this.value / 100
		resetDisks()
	})
	directionBar.addEventListener('change',function(){
		direction = this.value/(Math.PI*2)
		resetDisks()
	})
	//给调整加速度控件添加事件监听
	gravityBar.addEventListener('change', function() {
		
		
	})
}

//重置disks函数
function resetDisks() {
	clearInterval(loopId)
	ctx.clearRect(0, 0, canvas.width, canvas.height)
	disks = []
	generateDisks(numberOfDisks)
	main()
}

//生成disk的函数
function generateDisks(numberOfDisks) {
	for (let i = 0; i < numberOfDisks; i++) {
		disks.push(new Disk())
	}
}

//基础工具类，用于生成给定范围的随机整数
function randomInt(min, max) {
	return parseInt(Math.random() * (max - min + 1) + min * 1)
}

//用来生成画布中随机圆心坐标的函数
function getPosition() {
	var xPos, yPos
	xPos = randomInt(100, canvas.width - 100)
	yPos = randomInt(100, canvas.height - 100)
	//返回值类型为包含两个数的数组
	return [xPos, yPos]
}

//生成随机半径的函数
function getRadius(min, max) {
	return randomInt(min, max)
}

//随机颜色的函数
function getColor() {
	//三个通道的色阶在0-255范围内随机
	var redChannel = randomInt(0, 255)
	var greenChannel = randomInt(0, 255)
	var blueChannel = randomInt(0, 255)

	//将三个通道的颜色值拼接成16进制表达的字符串
	return '#' + redChannel.toString(16) + greenChannel.toString(16) + blueChannel.toString(16)

}

//定义生成随机初始速度的函数
function getOffsets(speed,direction) {
	//生成0-2Π之间随机长度的一段弧
	var radian
	if(direction>0){
		radian = direction
	}else{
		radian = Math.random() * 2 * Math.PI
	}
	
	//通过三角函数基于弧长分解速度
	var offsetX = Math.cos(radian) * speed
	var offsetY = Math.sin(radian) * speed
	return [offsetX, offsetY]
}

//定义Disk对象用于封装绘制disk所需要的属性跟方法
function Disk() {
	//用this关键字来定义disk的属性
	//各属性通过工具方法的调用来赋值
	this.color = getColor(); //颜色
	[this.xPos, this.yPos] = getPosition(); //圆心位置
	this.radius = getRadius(minRadius, maxRadius); //半径
	[this.offsetX, this.offsetY] = getOffsets(initialSpeed,direction) //速度
	this.hitBottom = 0
	this.temp = 0
	

	//定义Disk对象所拥有的方法
	//在画布上绘制当前的disk
	this.draw = function() {
		ctx.beginPath()
		ctx.fillStyle = this.color
		ctx.arc(this.xPos, this.yPos, this.radius, 0, 2 * Math.PI)
		ctx.fill()
	}
	//update方法用来定义绘制下一帧时disk属性有哪些变化
	this.update = function() {
		
		//边缘检测
		//水平边界检测
		if (this.xPos - this.radius <= 0 || this.xPos + this.radius >= canvas.width) {
			this.offsetX = -this.offsetX
		}
		
		//垂直边界检测
		//防止上下越界
		if (this.yPos + this.radius >= canvas.height) {
			
			this.yPos = canvas.height - this.radius
			this.offsetY = -this.offsetY
			
		} else if (this.yPos - this.radius <= 0) {
			
			this.yPos = this.radius
			this.offsetY = -this.offsetY

		}
		
		//改变下一帧圆心的位置
		this.xPos += this.offsetX
		this.yPos += this.offsetY
		
	}
}

function main() {
	//将数组中的disk依次绘制出来
	loopId = setInterval(function() {
		//绘制下一帧之前将当前画布内容清空
		ctx.clearRect(0, 0, canvas.width, canvas.height)
		//将数组中所有的disk依次绘制到画布上
		for (let i = 0; i < disks.length; i++) {
			disks[i].draw() //先画
			disks[i].update() //再更新当前disk在下一帧中出现的位置
		}
	}, 1000 / 60) //一般显示器的刷新率是60Hz，也就是1秒钟更新60帧，调用60次update()
}

//调用初始化函数
init()
//启动程序
main()
